package com.whmall.service.crm.module.company.service.impl;

import cn.hutool.json.JSONUtil;
import com.whmall.component.entity.dto.ApproveReqDTO;
import com.whmall.component.entity.dto.ProcessInstanceCompletedMessageReqDTO;
import com.whmall.component.entity.dto.UserTaskCompletedMessageReqDTO;
import com.whmall.component.entity.dto.UserTaskCreatedMessageReqDTO;
import com.whmall.component.util.FieldUtils;
import com.whmall.service.crm.entity.dto.company.*;
import com.whmall.service.crm.entity.dto.companyuser.CompanyUserAccountUpdateApplyDTO;
import com.whmall.service.crm.entity.dto.companyuser.CompanyUserNewUserApplyDTO;
import com.whmall.service.crm.entity.dto.companyuser.CompanyUserSupplierApplyDTO;
import com.whmall.service.crm.enumeration.CompanyAndUserApplicationTypeEnum;
import com.whmall.service.crm.module.company.dao.*;
import com.whmall.service.crm.module.company.entity.*;
import com.whmall.service.crm.module.company.entity.qo.CompanyAndUserApplicationInformationQO;
import com.whmall.service.crm.module.company.entity.qo.CompanyAndUserApplicationQO;
import com.whmall.service.crm.module.company.entity.qo.CompanyAndUserApproveInformationQO;
import com.whmall.service.crm.module.company.entity.qo.CompanyAndUserApproveQO;
import com.whmall.service.crm.module.company.service.CompanyAndUserApplicationService;
import com.whmall.service.crm.module.companyuser.dao.CompanyUserMapper;
import com.whmall.service.crm.module.companyuser.entity.CompanyUserDO;
import com.whmall.service.crm.module.companyuser.entity.qo.CompanyUserQO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CompanyAndUserApplicationServiceImpl implements CompanyAndUserApplicationService {

    @Autowired
    private CompanyAndUserApplicationMapper companyAndUserApplicationMapper;
    @Autowired
    private CompanyAndUserApplicationInformationMapper companyAndUserApplicationInfoMapper;
    @Autowired
    private CompanyAndUserApproveMapper companyAndUserApproveMapper;
    @Autowired
    private CompanyAndUserApproveInformationMapper companyAndUserApproveInfoMapper;
    @Autowired
    private CompanyUserMapper companyUserMapper;
    @Autowired
    private CompanyMapper companyMapper;

    @Override
    public Map<Long, CompanyAndUserApplicationRspDTO> selectByIds(List<Long> ids) {
        if(CollectionUtils.isEmpty(ids)){
            return Collections.emptyMap();
        }
        List<CompanyAndUserApplicationDO> applications = companyAndUserApplicationMapper.selectBy(
                CompanyAndUserApplicationQO.builder().ids(ids).build());
        Map<Long, CompanyAndUserApplicationInformationDO> infos = companyAndUserApplicationInfoMapper.selectBy(
                CompanyAndUserApplicationInformationQO.builder().ids(ids).build())
                .stream().collect(Collectors.toMap(e -> e.getId(), e -> e));
        //查询审批节点
        List<CompanyAndUserApproveDO> approveList = !applications.isEmpty() ?
                companyAndUserApproveMapper.selectBy(
                        CompanyAndUserApproveQO.builder()
                                .applicationIds(applications.stream().map(e -> e.getId()).collect(Collectors.toList()))
                                .isDeleted(0).isCancel(0).build())
                : Collections.emptyList();
        Map<Long, CompanyAndUserApproveInformationDO> approveInfos = !approveList.isEmpty() ?
                companyAndUserApproveInfoMapper.selectBy(
                        CompanyAndUserApproveInformationQO.builder()
                                .ids(approveList.stream().map(e -> e.getId()).collect(Collectors.toList()))
                                .build())
                .stream().collect(Collectors.toMap(e -> e.getId(), e -> e))
                : Collections.emptyMap();
        Map<Long, List<CompanyAndUserApplicationApproveRspDTO>> approves = approveList.stream()
                .collect(Collectors.groupingBy(e -> e.getApplicationId(),
                        Collectors.mapping(e -> {
                            CompanyAndUserApplicationApproveRspDTO approve = new CompanyAndUserApplicationApproveRspDTO();
                            BeanUtils.copyProperties(e, approve);
                            approve.setDeadlineTime(FieldUtils.unwrapDate(approve.getDeadlineTime()));
                            approve.setRemark(approveInfos.get(e.getId()).getRemark());
                            return approve;
                        }, Collectors.toList())));
        return applications.stream().collect(Collectors.toMap(e -> e.getId(), e -> {
            CompanyAndUserApplicationRspDTO rspDTO = new CompanyAndUserApplicationRspDTO();
            BeanUtils.copyProperties(e, rspDTO);
            BeanUtils.copyProperties(infos.get(e.getId()), rspDTO);
            rspDTO.setApproves(approves.get(e.getId()));
            return rspDTO;
        }));
    }

    @Override
    public List<CompanyAndUserApplicationRspDTO> selectBy(CompanyAndUserApplicationReqDTO reqDTO) {
        CompanyAndUserApplicationQO qo = new CompanyAndUserApplicationQO();
        BeanUtils.copyProperties(reqDTO, qo);
        return companyAndUserApplicationMapper.selectBy(qo)
                .stream().map(e -> {
                    CompanyAndUserApplicationRspDTO rspDTO = new CompanyAndUserApplicationRspDTO();
                    BeanUtils.copyProperties(e, rspDTO);
                    return rspDTO;
                }).collect(Collectors.toList());
    }

    @Transactional
    @Override
    public void createUserTask(UserTaskCreatedMessageReqDTO message) {
        Long applicationId = Long.valueOf(message.getBusinessId());
        CompanyAndUserApplicationDO application = companyAndUserApplicationMapper.selectById(applicationId);
        //补偿更新
        Date now = new Date();
        if(!StringUtils.hasText(application.getProcessInstanceId())){
            companyAndUserApplicationMapper.updateByIdSelective(
                    CompanyAndUserApplicationDO.builder()
                            .id(applicationId)
                            .processInstanceId(message.getProcessInstanceId())
                            .updateTime(now).build());
        }
        if(CollectionUtils.isEmpty(message.getVerifyIdList())){
            return;
        }
        //截止时间
        AtomicInteger i = new AtomicInteger();
        List<CompanyAndUserApproveDO> approveList = message.getVerifyIdList()
                .stream().map(verifyId -> {
                    CompanyAndUserApproveDO approve = CompanyAndUserApproveDO.builder()
                            .processInstanceId(message.getProcessInstanceId())
                            .applicationId(applicationId)
                            .approvalType(application.getApplicationType())
                            .companyId(application.getCompanyId())
                            .userId(application.getUserId())
                            .applicantId(application.getApplicantId())
                            .taskId(message.getTaskId())
                            .verifyId(verifyId)
                            .verifyDepartmentPath(message.getVerifyDepartmentPathList().get(i.getAndIncrement()))
                            .createTime(now)
                            .traderId(application.getTraderId())
                            .traderDepartmentPath(application.getTraderDepartmentPath())
                            .build();
                    companyAndUserApproveMapper.insertSelective(approve);
                    companyAndUserApproveInfoMapper.insertSelective(
                            CompanyAndUserApproveInformationDO.builder()
                            .id(approve.getId())
                            .nodeName(message.getNodeName())
                            .build());
                    return approve;
                }).collect(Collectors.toList());
    }

    @Transactional
    @Override
    public void verifyUserTask(UserTaskCompletedMessageReqDTO message) {
        List<Long> ids = companyAndUserApproveMapper.selectByTaskId(message.getTaskId())
                .stream().map(e -> e.getId()).collect(Collectors.toList());
        //如果是并签，更新全部人的记录
        if(!ids.isEmpty()){
            companyAndUserApproveMapper.updateByIds(
                    CompanyAndUserApproveQO.builder().ids(ids)
                            .nodeApprovalStatus(message.getNodeApprovalStatus())
                            .actualVerifyId(message.getVerifyId())
                            .verifyTime(message.getVerifyTime())
                            .build());
            if(StringUtils.hasText(message.getRemark())){
                companyAndUserApproveInfoMapper.updateByIds(
                        CompanyAndUserApproveInformationQO.builder().ids(ids)
                                .remark(message.getRemark()).build());
            }
        }
    }

    @Transactional
    @Override
    public Object finishWorkflow(ProcessInstanceCompletedMessageReqDTO message) {
        Long applicationId = Long.valueOf(message.getBusinessId());
        Assert.isTrue(message.getApprovalStatus() != null, "参数错误");//重要
        Date now = new Date();
        companyAndUserApplicationMapper.updateByIdSelective(
                CompanyAndUserApplicationDO.builder()
                        .id(applicationId)
                        .approvalStatus(message.getApprovalStatus())
                        .verifyTime(message.getFinishTime())
                        .updateTime(now)
                        .build());
        CompanyAndUserApplicationDO application = companyAndUserApplicationMapper.selectById(applicationId);
        String applicantParam = companyAndUserApplicationInfoMapper.selectById(applicationId).getApplicantParam();
        //审批通过的业务处理
        if(application.getApplicationType() == CompanyAndUserApplicationTypeEnum.NEW_USER_APPLICATION.getValue()){
            CompanyUserNewUserApplyDTO dto = JSONUtil.toBean(applicantParam, CompanyUserNewUserApplyDTO.class);
            dto.setApproveMessage(message);
            return dto;
        } else if (application.getApplicationType() == CompanyAndUserApplicationTypeEnum.ACCOUNT_UPDATE_APPLICATION.getValue()){
            CompanyUserAccountUpdateApplyDTO dto = JSONUtil.toBean(applicantParam, CompanyUserAccountUpdateApplyDTO.class);
            dto.setApproveMessage(message);
            return dto;
        } else if (application.getApplicationType() == CompanyAndUserApplicationTypeEnum.SUPPLIER_POWER_APPLICATION.getValue()){
            CompanyUserSupplierApplyDTO dto = JSONUtil.toBean(applicantParam, CompanyUserSupplierApplyDTO.class);
            dto.setApproveMessage(message);
            return dto;
        } else if (application.getApplicationType() == CompanyAndUserApplicationTypeEnum.COMPANY_UPDATE_APPLICATION.getValue()){
            CompanyUpdateApplyDTO dto = JSONUtil.toBean(applicantParam, CompanyUpdateApplyDTO.class);
            dto.setApproveMessage(message);
            return dto;
        } else if (application.getApplicationType() == CompanyAndUserApplicationTypeEnum.COMPANY_BASIC_APPLICATION.getValue()){
            CompanyBasicInfoApplyDTO dto = JSONUtil.toBean(applicantParam, CompanyBasicInfoApplyDTO.class);
            return dto;
        }
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateApplicantParam(ApproveReqDTO reqDTO) {
        if(!StringUtils.hasText(reqDTO.getApplicantParam())){
            return;
        }
        Long applicationId = companyAndUserApproveMapper.selectByTaskId(reqDTO.getTaskId())
                .get(0).getApplicationId();
        CompanyAndUserApplicationDO application = companyAndUserApplicationMapper.selectById(applicationId);
        CompanyAndUserApplicationInformationDO applicationInfo = companyAndUserApplicationInfoMapper.selectById(applicationId);
        if(application.getApplicationType() == CompanyAndUserApplicationTypeEnum.NEW_USER_APPLICATION.getValue()){
            CompanyUserNewUserApplyDTO dto = JSONUtil.toBean(applicationInfo.getApplicantParam(), CompanyUserNewUserApplyDTO.class);
            CompanyUserNewUserApplyDTO dtoNew = JSONUtil.toBean(reqDTO.getApplicantParam(), CompanyUserNewUserApplyDTO.class);
            Long id = dto.getId();
            BeanUtils.copyProperties(dtoNew, dto);
            dto.setId(id);
            reqDTO.setApplicantParam(JSONUtil.toJsonStr(dto));
            if(StringUtils.hasText(dtoNew.getMobile())){
                List<CompanyUserDO> users = companyUserMapper.listBy(CompanyUserQO.builder()
                        .mobile(dtoNew.getMobile()).build());
                Assert.isTrue(users.isEmpty() || users.get(0).getId() == dto.getId().longValue(), "该手机号已被使用");
            }
            if(StringUtils.hasText(dtoNew.getEmail())){
                List<CompanyUserDO> users = companyUserMapper.listBy(CompanyUserQO.builder()
                        .email(dtoNew.getEmail()).build());
                Assert.isTrue(users.isEmpty() || users.get(0).getId() == dto.getId().longValue(), "该邮箱已被使用");
            }
        } else if (application.getApplicationType() == CompanyAndUserApplicationTypeEnum.ACCOUNT_UPDATE_APPLICATION.getValue()){
            CompanyUserAccountUpdateApplyDTO dto = JSONUtil.toBean(applicationInfo.getApplicantParam(), CompanyUserAccountUpdateApplyDTO.class);
            CompanyUserAccountUpdateApplyDTO dtoNew = JSONUtil.toBean(reqDTO.getApplicantParam(), CompanyUserAccountUpdateApplyDTO.class);
            dto.setName(dtoNew.getName());
            dto.setMobile(dtoNew.getMobile());
            dto.setEmail(dtoNew.getEmail());
            reqDTO.setApplicantParam(JSONUtil.toJsonStr(dto));
            if(StringUtils.hasText(dtoNew.getMobile())){
                List<CompanyUserDO> users = companyUserMapper.listBy(CompanyUserQO.builder()
                        .mobile(dtoNew.getMobile()).build());
                Assert.isTrue(users.isEmpty() || users.get(0).getId() == dto.getId().longValue(), "该手机号已被使用");
            }
            if(StringUtils.hasText(dtoNew.getEmail())){
                List<CompanyUserDO> users = companyUserMapper.listBy(CompanyUserQO.builder()
                        .email(dtoNew.getEmail()).build());
                Assert.isTrue(users.isEmpty() || users.get(0).getId() == dto.getId().longValue(), "该邮箱已被使用");
            }
        } else if (application.getApplicationType() == CompanyAndUserApplicationTypeEnum.SUPPLIER_POWER_APPLICATION.getValue()){
            CompanyUserSupplierApplyDTO dto = JSONUtil.toBean(applicationInfo.getApplicantParam(), CompanyUserSupplierApplyDTO.class);
            CompanyUserSupplierApplyDTO dtoNew = JSONUtil.toBean(reqDTO.getApplicantParam(), CompanyUserSupplierApplyDTO.class);
            Long id = dto.getId();
            BeanUtils.copyProperties(dtoNew, dto);
            dto.setId(id);
            reqDTO.setApplicantParam(JSONUtil.toJsonStr(dto));
        } else if (application.getApplicationType() == CompanyAndUserApplicationTypeEnum.COMPANY_UPDATE_APPLICATION.getValue()){
            CompanyUpdateApplyDTO dto = JSONUtil.toBean(applicationInfo.getApplicantParam(), CompanyUpdateApplyDTO.class);
            CompanyUpdateApplyDTO dtoNew = JSONUtil.toBean(reqDTO.getApplicantParam(), CompanyUpdateApplyDTO.class);
            Long id = dto.getId();
            BeanUtils.copyProperties(dtoNew, dto);
            dto.setId(id);
            reqDTO.setApplicantParam(JSONUtil.toJsonStr(dto));
            if(StringUtils.hasText(dtoNew.getName())){
                CompanyDO company = companyMapper.getByName(dtoNew.getName());
                Assert.isTrue(company == null || company.getId() == dto.getId().longValue(), "该公司名称已被使用");
            }
        } else if (application.getApplicationType() == CompanyAndUserApplicationTypeEnum.COMPANY_BASIC_APPLICATION.getValue()){
            CompanyBasicInfoApplyDTO dto = JSONUtil.toBean(applicationInfo.getApplicantParam(), CompanyBasicInfoApplyDTO.class);
            CompanyBasicInfoApplyDTO dtoNew = JSONUtil.toBean(reqDTO.getApplicantParam(), CompanyBasicInfoApplyDTO.class);
            Long id = dto.getId();
            BeanUtils.copyProperties(dtoNew, dto);
            dto.setId(id);
            reqDTO.setApplicantParam(JSONUtil.toJsonStr(dto));
            if(StringUtils.hasText(dtoNew.getName())){
                CompanyDO company = companyMapper.getByName(dtoNew.getName());
                Assert.isTrue(company == null || company.getId() == dto.getId().longValue(), "该公司名称已被使用");
            }
        }
        companyAndUserApplicationInfoMapper.updateByIdSelective(
                CompanyAndUserApplicationInformationDO.builder()
                        .id(applicationId)
                        .applicantParam(reqDTO.getApplicantParam()).build());
    }

    @Override
    public void updateProcessInstanceId(Long id, String processInstanceId) {
        companyAndUserApplicationMapper.updateByIdSelective(CompanyAndUserApplicationDO.builder()
                .id(id)
                .processInstanceId(processInstanceId)
                .build());
    }

}
